package com.snail.file.service.impl;


import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.snail.common.core.utils.PageUtils;
import com.snail.common.core.utils.StringUtils;
import com.snail.common.core.utils.file.FileUtils;
import com.snail.common.core.web.page.PageResult;
import com.snail.file.config.FileConfigProperties;
import com.snail.file.constants.FileConstants;
import com.snail.file.exception.FileException;
import com.snail.file.mapper.SysFileMapper;
import com.snail.file.service.ISysFileService;
import com.snail.system.api.domain.SysFile;
import com.snail.system.api.query.SysFileQuery;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * @Description: 文件信息Service业务层处理
 * @Author: snail
 * @CreateDate: 2023-09-20
 * @Version: V1.0
 */
@Service
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements ISysFileService {

    @Autowired
    private FileConfigProperties properties;
    @Autowired
    private LocalSysFileServiceImpl localSysFileService;
    @Autowired
    private MinioSysFileServiceImpl minioSysFileService;
    @Autowired
    private FastDfsSysFileServiceImpl fastDfsSysFileService;

    @SneakyThrows
    @Override
    public SysFile uploadFile(MultipartFile file, String bizKey) {
        String url = "";
        switch (properties.getServerType()) {
            case FileConstants.LOCAL:
                url = localSysFileService.uploadFile(file);
                break;
            case FileConstants.MINIO:
                url = minioSysFileService.uploadFile(file);
                break;
            case FileConstants.FAST_DFS:
                url = fastDfsSysFileService.uploadFile(file);
                break;
            default:
        }
        if (StringUtils.isBlank(url)) {
            throw new FileException("文件上传失败!");
        }
        SysFile sysFile = new SysFile();
        sysFile.setBizKey(bizKey);
        sysFile.setFileName(FileUtils.getName(url));
        sysFile.setFileUrl(url);
        sysFile.setFileSize(BigDecimal.valueOf(file.getSize()).divide(BigDecimal.valueOf(1024), RoundingMode.UP));
        this.save(sysFile);
        return sysFile;
    }

    @Override
    public PageResult<SysFile> getSysFilePage(SysFileQuery query) {
        Page<SysFile> page = PageUtils.buildPage(query);
        LambdaQueryWrapper<SysFile> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysFile::getBizKey, query.getBizKey());
        queryWrapper.like(StringUtils.isNotEmpty(query.getFileName()), SysFile::getFileName, query.getFileName());
        page = this.baseMapper.selectPage(page, queryWrapper);
        page.getRecords().forEach(e -> {
            if (FileConstants.MINIO.equals(properties.getServerType())) {
                e.setFileUrl(properties.getMinio().getUrl() + "/" + properties.getMinio().getBucketName() + "/" + e.getFileUrl());
            }
        });
        return PageUtils.pageResult(page);
    }

    @Override
    public List<SysFile> selectSysFileList(SysFileQuery query) {
        LambdaQueryWrapper<SysFile> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysFile::getBizKey, query.getBizKey());
        queryWrapper.like(StringUtils.isNotEmpty(query.getFileName()), SysFile::getFileName, query.getFileName());
        List<SysFile> sysFiles = this.baseMapper.selectList(queryWrapper);
        sysFiles.forEach(e -> {
            if (FileConstants.MINIO.equals(properties.getServerType())) {
                e.setFileUrl(properties.getMinio().getUrl() + "/" + properties.getMinio().getBucketName() + "/" + e.getFileUrl());
            }
        });
        return sysFiles;
    }

    @SneakyThrows
    @Override
    public void download(HttpServletResponse response, String fileId) {
        SysFile file = getById(fileId);
        if (file == null) {
            throw new FileException("文件不存在!");
        }
        InputStream is = null;
        switch (properties.getServerType()) {
            case FileConstants.LOCAL:
                is = localSysFileService.download(file);
                break;
            case FileConstants.MINIO:
                is = minioSysFileService.download(file);
                break;
            case FileConstants.FAST_DFS:
                is = fastDfsSysFileService.download(file);
                break;
            default:
        }
        if (is == null) {
            throw new FileException("文件不存在!");
        }
        FileUtils.setAttachmentResponseHeader(response, file.getFileName());
        // 循环取出流中的数据
        byte[] b = new byte[100];
        int len;
        try {
            while ((len = is.read(b)) > 0) {
                response.getOutputStream().write(b, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            is.close();
        }
    }

    @SneakyThrows
    @Override
    public boolean deleteFile(String fileId) {
        SysFile file = getById(fileId);
        if (file == null) {
            throw new FileException("文件不存在!");
        }
        switch (properties.getServerType()) {
            case FileConstants.LOCAL:
                localSysFileService.delete(file);
                break;
            case FileConstants.MINIO:
                minioSysFileService.delete(file);
                break;
            case FileConstants.FAST_DFS:
                fastDfsSysFileService.delete(file);
                break;
            default:
        }
        this.baseMapper.deleteById(fileId);
        return true;
    }
}
